/**
 * Copyright (c) 2009-2011, chunquedong(YangJiandong)
 * 
 * This file is part of ChunMap project
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE(Version >=3)
 * 
 * History:
 *     2010-05-05  Jed Young  Creation
 */
package chunmap.data.provider.shp;

import java.io.File;
import java.nio.charset.Charset;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Arrays;

import chunmap.data.ChunMapDataException;
import chunmap.data.feature.FeatureSchama;
import chunmap.data.feature.Field;
import chunmap.util.Logger;

public class DbfReader {
	private static final Logger Log=new Logger(Logger.Off,DbfReader.class.getName());
	
	private ResultSet resultSet;
	private Connection connDbf = null;
	private PreparedStatement psDbf = null;
	private FeatureSchama featureSchama;
	private Charset charset;
	
	public DbfReader(String path) {
		open(path);
	}

	public Object[] getValues(long index){
		try{
			while(resultSet.next()){
				if(resultSet.getRow()==index+1){
					int n=resultSet.getMetaData().getColumnCount();
					
					Object[] values=new Object[n];
					for(int i=0;i<n;i++){
						values[i]=readData(resultSet,i);
					}
					Log.debug(Arrays.toString(values));
					return values;
				}
			}
			throw new ChunMapDataException("no data in index="+index);
		}catch (SQLException e) {
			throw new ChunMapDataException(e);
		}
	}
	
	private Object readData(ResultSet resultSet,int i) throws SQLException{
		int dataType=resultSet.getMetaData().getColumnType(i+1);
		if(charset !=null && (dataType==Types.CHAR || dataType==Types.VARCHAR)){
			byte[] bs=resultSet.getBytes(i+1);
			if(bs==null)return "";
			byte[] bs2 = new String(bs,charset).getBytes();
			//return new String(bs2,Charset.forName("UTF-8"));
			return new String(bs2);
		}
		
		return resultSet.getObject(i+1);
	}
	
	public void close(){
		try {
			resultSet.close();
			psDbf.close();
			connDbf.close();
			
		} catch (SQLException e) {
			throw new ChunMapDataException(e);
		}
	}

	private void open(String apath){
		try {
			readDbf(apath);
			featureSchama=loadFeatureSchama();
			
		} catch (ClassNotFoundException e) {
			throw new ChunMapDataException(e);
		} catch (SQLException e) {
			throw new ChunMapDataException(e);
		}
	}

	private void readDbf(String apath) throws ClassNotFoundException, SQLException{
		File file = new File(apath);
		String name = file.getName();
		name=name.substring(0,name.lastIndexOf("."));
		String path = apath.substring(0, apath.lastIndexOf(File.separator));
		
		Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
		connDbf = DriverManager.getConnection(
				"jdbc:odbc:DRIVER={Microsoft dBase Driver (*.dbf)};DBQ=" 
				+ path + ";","","");
		String sql = "select * from " + name;
		psDbf = connDbf.prepareStatement(sql);
		resultSet = psDbf.executeQuery();
	}

	private FeatureSchama loadFeatureSchama() throws SQLException{
		ResultSetMetaData rm= resultSet.getMetaData();
		int n=rm.getColumnCount();
		
		Field[] fields=new Field[n];
		for(int i=0;i<n;i++){
			Field f=new Field(rm.getColumnName(i+1),i,rm.getColumnType(i+1));
			fields[i]=f;
		}
		FeatureSchama fs=new FeatureSchama(fields,-1,-1);
		return fs;
	}

	public FeatureSchama getFeatureSchama() {
		return featureSchama;
	}

	public void setCharset(Charset charset) {
		this.charset = charset;
	}
}